/**
  ******************************************************************************
  * File Name          : measaccrue.c
  * Description        : Code for freertos applications
  ******************************************************************************
  * @attention : 注意单位!!! 
  *
  ******************************************************************************
  */

/* Includes ------------------------------------------------------------------*/
#include "bsp.h"
#include "tskcfg.h"
#include "measure.h"
#include "gv.h"
#include "parameter.h"
#include "produp.h"

typedef struct _acc_keydata_stru
{
  uint32_t class01_start;
  uint32_t class02_start;
  uint32_t class03_start;
  uint32_t class04_start;
  uint32_t nowtime;
  Sys_DataTimeStru locktime;
}acc_keydata_stru;

/* 分度与示值转换 */
uint64_t meas_division_indication(uint64_t dsrc, uint8_t interval)
{
  uint32_t  div = 1;
  uint64_t  isrc;

  isrc = (uint64_t)(dsrc/10000);  /* 将0.1g累计原始值转成kg的整数 */

  switch(interval)
  {
    case 1:
      div = 2;
      break;
    
    case 2:
      div = 5;
      break;
    
    case 3:
      div = 10;
      break;
    
    case 4:
      div = 20;
      break;
    
    case 5:
      div = 50;
      break;
    
    case 6:
      div = 100;
      break;
    
    case 7:
      div = 200;
      break;
    
    case 8:
      div = 500;
      break;
    
    case 9:
      div = 1000;
      break;
    
    case 0:
    default:
      div = 1;
      return isrc;
  }
  
	if(isrc % div != 0)
	{
		if((2 * (isrc % div) == 0) || (2 * (isrc % div) >= div)){
			isrc /= div;
			isrc *= div;
			isrc += div;
		}else{
			isrc /= div;
			isrc *= div;
		}
	}
	
	return isrc;
}

static inline void acc_class_now(GlobalVariablesStru *pgv, acc_keydata_stru *kd)
{
  kd->locktime = sys_datatime;
  kd->nowtime  = (sys_datatime.hour*3600) + (sys_datatime.minute*60) + sys_datatime.second;

  kd->class01_start = pgv->hr.meas_pa.acc_class01_start_time;
  kd->class02_start = pgv->hr.meas_pa.acc_class02_start_time;
  kd->class03_start = pgv->hr.meas_pa.acc_class03_start_time;
  kd->class04_start = pgv->hr.meas_pa.acc_class04_start_time;
  
  switch(pgv->hr.meas_pa.num_of_class)
  {
    case 0: /* 仅有1个班时 */
      pgv->ir.meas_ca.current_class = 0;
      break;

    case 1: /* 仅有2个班时 */
      if((kd->nowtime >= kd->class01_start) && (kd->nowtime < kd->class02_start))
      {
        pgv->ir.meas_ca.current_class = 0;
      }
      else if ((kd->nowtime >= kd->class02_start) && (kd->nowtime <= 235959))
      {
        pgv->ir.meas_ca.current_class = 1;
      }
      break;

    case 2: /* 仅有3个班时 */
      if((kd->nowtime >= kd->class01_start) && (kd->nowtime < kd->class02_start))
      {
        pgv->ir.meas_ca.current_class = 0;
      }
      else if ((kd->nowtime >= kd->class02_start) && (kd->nowtime < kd->class03_start))
      {
        pgv->ir.meas_ca.current_class = 1;
      }
      else if ((kd->nowtime >= kd->class03_start) && (kd->nowtime <= 235959))
      {
        pgv->ir.meas_ca.current_class = 2;
      }
      break;

    case 3: /* 仅有4个班时 */
    default:
      if((kd->nowtime >= kd->class01_start) && (kd->nowtime < kd->class02_start))
      {
        pgv->ir.meas_ca.current_class = 0;
      }
      else if ((kd->nowtime >= kd->class02_start) && (kd->nowtime < kd->class03_start))
      {
        pgv->ir.meas_ca.current_class = 1;
      }
      else if ((kd->nowtime >= kd->class03_start) && (kd->nowtime < kd->class04_start))
      {
        pgv->ir.meas_ca.current_class = 2;
      }
      else if ((kd->nowtime >= kd->class04_start) && (kd->nowtime <= 235959))
      {
        pgv->ir.meas_ca.current_class = 3;
      }
      break;
  }
}

static inline void acc_total_clear(GlobalVariablesStru *pgv, const acc_keydata_stru *kd, uint8_t a0m1)
{
  Sys_DataTimeStru clear_time;

  clear_time = kd->locktime;
  clear_time.a0m1 = a0m1;

  pgv->ir.meas_ca.total_acc_last_0d1g = pgv->ir.meas_ca.total_acc_0d1g;
  pgv->ir.meas_ca.total_acc_0d1g = 0;
  
  sto_update_item(sto_mtidx(total_acc_0d1g),     (const Sto_CellUnion *)&pgv->ir.meas_ca.total_acc_0d1g,      1);
  sto_update_item(sto_mtidx(total_acc_last_0d1g),(const Sto_CellUnion *)&pgv->ir.meas_ca.total_acc_last_0d1g, 1);
  sto_update_item(sto_mtidx(total_last_switch),    (const Sto_CellUnion *)&clear_time, 1);
}

static inline void acc_year_clear(GlobalVariablesStru *pgv, const acc_keydata_stru *kd, uint8_t a0m1)
{
  Sys_DataTimeStru clear_time;

  clear_time = kd->locktime;
  clear_time.a0m1 = a0m1;

  pgv->ir.meas_ca.year_acc_last_0d1g = pgv->ir.meas_ca.year_acc_0d1g;
  pgv->ir.meas_ca.year_acc_0d1g = 0;
  
  sto_update_item(sto_mtidx(year_acc_0d1g),     (const Sto_CellUnion *)&pgv->ir.meas_ca.year_acc_0d1g,      1);
  sto_update_item(sto_mtidx(year_acc_last_0d1g),(const Sto_CellUnion *)&pgv->ir.meas_ca.year_acc_last_0d1g, 1);
  sto_update_item(sto_mtidx(year_last_switch),    (const Sto_CellUnion *)&clear_time, 1);
}

static inline void acc_month_clear(GlobalVariablesStru *pgv, const acc_keydata_stru *kd, uint8_t a0m1)
{
  Sys_DataTimeStru clear_time;

  clear_time = kd->locktime;
  clear_time.a0m1 = a0m1;

  pgv->ir.meas_ca.month_acc_last_0d1g = pgv->ir.meas_ca.month_acc_0d1g;
  pgv->ir.meas_ca.month_acc_0d1g = 0;
  
  sto_update_item(sto_mtidx(month_acc_0d1g),     (const Sto_CellUnion *)&pgv->ir.meas_ca.month_acc_0d1g,      1);
  sto_update_item(sto_mtidx(month_acc_last_0d1g),(const Sto_CellUnion *)&pgv->ir.meas_ca.month_acc_last_0d1g, 1);
  sto_update_item(sto_mtidx(month_last_switch),    (const Sto_CellUnion *)&clear_time, 1);
}

static inline void acc_day_clear(GlobalVariablesStru *pgv, const acc_keydata_stru *kd, uint8_t a0m1)
{
  Sys_DataTimeStru clear_time;

  clear_time = kd->locktime;
  clear_time.a0m1 = a0m1;

  pgv->ir.meas_ca.day_acc_last_0d1g = pgv->ir.meas_ca.day_acc_0d1g;
  pgv->ir.meas_ca.day_acc_0d1g = 0;
  
  sto_update_item(sto_mtidx(day_acc_0d1g),     (const Sto_CellUnion *)&pgv->ir.meas_ca.day_acc_0d1g,      1);
  sto_update_item(sto_mtidx(day_acc_last_0d1g),(const Sto_CellUnion *)&pgv->ir.meas_ca.day_acc_last_0d1g, 1);
  sto_update_item(sto_mtidx(day_last_switch),    (const Sto_CellUnion *)&clear_time, 1);
}

static inline void acc_hour_clear(GlobalVariablesStru *pgv, const acc_keydata_stru *kd, uint8_t a0m1)
{
  Sys_DataTimeStru clear_time;

  clear_time = kd->locktime;
  clear_time.a0m1 = a0m1;

  pgv->ir.meas_ca.hour_acc_last_0d1g = pgv->ir.meas_ca.hour_acc_0d1g;
  pgv->ir.meas_ca.hour_acc_0d1g = 0;
  
  sto_update_item(sto_mtidx(hour_acc_0d1g),     (const Sto_CellUnion *)&pgv->ir.meas_ca.hour_acc_0d1g,      1);
  sto_update_item(sto_mtidx(hour_acc_last_0d1g),(const Sto_CellUnion *)&pgv->ir.meas_ca.hour_acc_last_0d1g, 1);
  sto_update_item(sto_mtidx(hour_last_switch),  (const Sto_CellUnion *)&clear_time, 1);
}

static void acc_class_clear(GlobalVariablesStru *pgv, const acc_keydata_stru *kd, uint8_t a0m1)
{
  Sys_DataTimeStru clear_time;
  
  clear_time = kd->locktime;
  clear_time.a0m1 = a0m1;
  
  pgv->ir.meas_ca.class01_acc_last_0d1g = pgv->ir.meas_ca.class01_acc_0d1g;
  pgv->ir.meas_ca.class01_acc_0d1g = 0;
  
  pgv->ir.meas_ca.class02_acc_last_0d1g = pgv->ir.meas_ca.class02_acc_0d1g;
  pgv->ir.meas_ca.class02_acc_0d1g = 0;

  pgv->ir.meas_ca.class03_acc_last_0d1g = pgv->ir.meas_ca.class03_acc_0d1g;
  pgv->ir.meas_ca.class03_acc_0d1g = 0;

  pgv->ir.meas_ca.class04_acc_last_0d1g = pgv->ir.meas_ca.class04_acc_0d1g;
  pgv->ir.meas_ca.class04_acc_0d1g = 0;

  sto_update_item(sto_mtidx(class01_acc_0d1g),     (const Sto_CellUnion *)&pgv->ir.meas_ca.class01_acc_0d1g, 1);
  sto_update_item(sto_mtidx(class01_acc_last_0d1g),(const Sto_CellUnion *)&pgv->ir.meas_ca.class01_acc_last_0d1g, 1);

  sto_update_item(sto_mtidx(class02_acc_0d1g),     (const Sto_CellUnion *)&pgv->ir.meas_ca.class02_acc_0d1g, 1);
  sto_update_item(sto_mtidx(class02_acc_last_0d1g),(const Sto_CellUnion *)&pgv->ir.meas_ca.class02_acc_last_0d1g, 1);

  sto_update_item(sto_mtidx(class03_acc_0d1g),     (const Sto_CellUnion *)&pgv->ir.meas_ca.class03_acc_0d1g, 1);
  sto_update_item(sto_mtidx(class03_acc_last_0d1g),(const Sto_CellUnion *)&pgv->ir.meas_ca.class03_acc_last_0d1g, 1);

  sto_update_item(sto_mtidx(class04_acc_0d1g),     (const Sto_CellUnion *)&pgv->ir.meas_ca.class04_acc_0d1g, 1);
  sto_update_item(sto_mtidx(class04_acc_last_0d1g),(const Sto_CellUnion *)&pgv->ir.meas_ca.class04_acc_last_0d1g, 1);

  sto_update_item(sto_mtidx(class_last_switch),      (const Sto_CellUnion *)&clear_time, 1);
}

static void acc_total_save(GlobalVariablesStru *pgv)
{
  /* 总累计没有自动切换清零 */
  sto_update_item(sto_mtidx(total_acc_0d1g), (const Sto_CellUnion *)&pgv->ir.meas_ca.total_acc_0d1g, 2);
}

static void acc_year_save(GlobalVariablesStru *pgv, const acc_keydata_stru *kd)
{
  if(sys_datatime.year != pgv->ir.meas_ca.wtacc_year_last_switch.year)
  {
    if(pgv->hr.meas_pa.day_begin_zero == MEAS_BEGIN_ZERO_CLASS01ST)
    {
      if((sys_datatime.month != 1) || (sys_datatime.day != 1) || (kd->nowtime >= kd->class01_start))
      {
        acc_year_clear(pgv, kd, 0);
        return;
      }
    }
    else
    {
      acc_year_clear(pgv, kd, 0);
      return;
    }
  }
  
  sto_update_item(sto_mtidx(year_acc_0d1g), (const Sto_CellUnion *)&pgv->ir.meas_ca.year_acc_0d1g, 2);
}

static void acc_month_save(GlobalVariablesStru *pgv, const acc_keydata_stru *kd)
{
  if((sys_datatime.month != pgv->ir.meas_ca.wtacc_month_last_switch.month) || \
     (sys_datatime.year  != pgv->ir.meas_ca.wtacc_month_last_switch.year))
  {
    if(pgv->hr.meas_pa.month_begin_zero == MEAS_BEGIN_ZERO_CLASS01ST)
    {
      if((sys_datatime.day != 1) || (kd->nowtime >= kd->class01_start))
      {
        acc_month_clear(pgv, kd, 0);
        return;
      }
    }
    else
    {
      acc_month_clear(pgv, kd, 0);
      return;
    }
  }
  
  sto_update_item(sto_mtidx(month_acc_0d1g), (const Sto_CellUnion *)&pgv->ir.meas_ca.month_acc_0d1g, 2);
}

static void acc_day_save(GlobalVariablesStru *pgv, const acc_keydata_stru *kd)
{
  if((sys_datatime.day   != pgv->ir.meas_ca.wtacc_day_last_switch.day)   || \
     (sys_datatime.month != pgv->ir.meas_ca.wtacc_day_last_switch.month) || \
     (sys_datatime.year  != pgv->ir.meas_ca.wtacc_day_last_switch.year))
  {
    if(pgv->hr.meas_pa.day_begin_zero == MEAS_BEGIN_ZERO_CLASS01ST)
    {
      if(kd->nowtime >= kd->class01_start)
      {
        acc_day_clear(pgv, kd, 0);
        return;
      }
    }
    else
    {
      acc_day_clear(pgv, kd, 0);
      return;
    }
  }
  
  sto_update_item(sto_mtidx(day_acc_0d1g), (const Sto_CellUnion *)&pgv->ir.meas_ca.day_acc_0d1g, 2);
}

static void acc_hour_save(GlobalVariablesStru *pgv, const acc_keydata_stru *kd)
{
  if((sys_datatime.hour  != pgv->ir.meas_ca.wtacc_hour_last_switch.hour)  || \
     (sys_datatime.day   != pgv->ir.meas_ca.wtacc_hour_last_switch.day)   || \
     (sys_datatime.month != pgv->ir.meas_ca.wtacc_hour_last_switch.month) || \
     (sys_datatime.year  != pgv->ir.meas_ca.wtacc_hour_last_switch.year))
  {
    /* 小时累计没有起始时期之分 */
    acc_hour_clear(pgv, kd, 0);
    return;
  }

  sto_update_item(sto_mtidx(hour_acc_0d1g), (const Sto_CellUnion *)&pgv->ir.meas_ca.hour_acc_0d1g, 2);
}

static void acc_class_save(GlobalVariablesStru *pgv, const acc_keydata_stru *kd)
{
  if((kd->locktime.day   != pgv->ir.meas_ca.wtacc_day_last_switch.day)   || \
     (kd->locktime.month != pgv->ir.meas_ca.wtacc_day_last_switch.month) || \
     (kd->locktime.year  != pgv->ir.meas_ca.wtacc_day_last_switch.year))
  {
    if(kd->nowtime >= kd->class01_start)
    {
      acc_class_clear(pgv, kd, 0);
      return;
    }
  }

  sto_update_item(sto_mtidx(class01_acc_0d1g), (const Sto_CellUnion *)&pgv->ir.meas_ca.class01_acc_0d1g, 1);
  sto_update_item(sto_mtidx(class02_acc_0d1g), (const Sto_CellUnion *)&pgv->ir.meas_ca.class02_acc_0d1g, 1);
  sto_update_item(sto_mtidx(class03_acc_0d1g), (const Sto_CellUnion *)&pgv->ir.meas_ca.class03_acc_0d1g, 1);
  sto_update_item(sto_mtidx(class04_acc_0d1g), (const Sto_CellUnion *)&pgv->ir.meas_ca.class04_acc_0d1g, 1);
}

static void meas_interval_accrue(double flowrate_0d1g_0d01s, GlobalVariablesStru *pgv)
{
  static uint32_t cnt = 0;
  Prod_DataBaseStru proddb;

  if(cnt >= (pgv->hr.meas_pa.prod_interval_time_s * 100))
  {
    cnt = 0;

    /* 锁存产量数据 发送给产量任务 */
    proddb.year = sys_datatime.year + 2000;
    proddb.month = sys_datatime.month;
    proddb.day = sys_datatime.day;
    proddb.hour = sys_datatime.hour;
    proddb.minute = sys_datatime.minute;
    proddb.second = sys_datatime.second;

    proddb.belt_speed_mms    = pgv->ir.meas_ca.belt_speed_mms;
    proddb.flowrate_kgh      = pgv->ir.meas_ca.flowrate_kgh;
    proddb.interval_acc_0d1g = pgv->ir.meas_ca.interval_acc_0d1g;
    proddb.total_acc_0d1g    = pgv->ir.meas_ca.total_acc_0d1g;
    proddb.year_acc_0d1g     = pgv->ir.meas_ca.year_acc_0d1g;
    proddb.month_acc_0d1g    = pgv->ir.meas_ca.month_acc_0d1g;
    proddb.day_acc_0d1g      = pgv->ir.meas_ca.day_acc_0d1g;
    proddb.hour_acc_0d1g     = pgv->ir.meas_ca.hour_acc_0d1g;
    
    xQueueSend(prod_database_qhd, &proddb, 0);

    pgv->ir.meas_ca.interval_acc_0d1g = 0;
  }

  cnt++;

  pgv->ir.meas_ca.interval_acc_0d1g += flowrate_0d1g_0d01s;
}

static void meas_tymd_accrue(double flowrate_0d1g_0d01s, GlobalVariablesStru *pgv, const acc_keydata_stru *kd)
{
  static uint8_t step = 0;

  if(step++ > 99)
  {
    step = 0;

    acc_total_save(pgv);
    acc_hour_save(pgv, kd);
    acc_day_save(pgv, kd);
    acc_month_save(pgv, kd);
    acc_year_save(pgv, kd);
  }
  
  if(flowrate_0d1g_0d01s <= 0.0)  /* 如果流量为负值,不做累计 */
  {
    return;
  }
  
  pgv->ir.meas_ca.total_acc_0d1g += flowrate_0d1g_0d01s;
  pgv->ir.meas_ca.year_acc_0d1g  += flowrate_0d1g_0d01s;
  pgv->ir.meas_ca.month_acc_0d1g += flowrate_0d1g_0d01s;
  pgv->ir.meas_ca.day_acc_0d1g   += flowrate_0d1g_0d01s;
  pgv->ir.meas_ca.hour_acc_0d1g  += flowrate_0d1g_0d01s;
}

static void meas_class_accrue(double flowrate_0d1g_0d01s, GlobalVariablesStru *pgv, const acc_keydata_stru *kd)
{
  static uint8_t step = 0;

  if(step++ > 100)  /* 如果改了频率 注意在次调整 */
  {
    step = 0;

    acc_class_save(pgv, kd);
  }
  
  if(flowrate_0d1g_0d01s <= 0.0)  /* 如果流量为负值,不做累计 */
  {
    return;
  }

  switch(pgv->ir.meas_ca.current_class)
  {
    case 0:
      pgv->ir.meas_ca.class01_acc_0d1g += flowrate_0d1g_0d01s;
      break;

    case 1:
      pgv->ir.meas_ca.class02_acc_0d1g += flowrate_0d1g_0d01s;
      break;

    case 2:
      pgv->ir.meas_ca.class03_acc_0d1g += flowrate_0d1g_0d01s;
      break;

    case 3:
      pgv->ir.meas_ca.class04_acc_0d1g += flowrate_0d1g_0d01s;
      break;

    default:
      break;
  }
}

double meas_get_current_class_prod(GlobalVariablesStru *pgv)
{
  switch(pgv->ir.meas_ca.current_class)
  {
    case 0:
      return pgv->ir.meas_ca.class01_acc_0d1g;

    case 1:
      return pgv->ir.meas_ca.class02_acc_0d1g;

    case 2:
      return pgv->ir.meas_ca.class03_acc_0d1g;

    case 3:
      return pgv->ir.meas_ca.class04_acc_0d1g;

    default:
      return 0.0;
  }
  
  return 0.0;
}

void meas_pulse_accrue(double flowrate_0d1g_0d01s, GlobalVariablesStru *pgv)
{
  static uint8_t step = 0;
  uint8_t force_save;
  uint32_t set_0d1g;

  if(pgv->hr.meas_pa.weight_pulse_wide < 1)
  {
    if(pgv->ir.meas_ca.pulse_acc_0d1g != 0)
    {
      pgv->ir.meas_ca.pulse_acc_0d1g = 0;
      pgv->ir.meas_ca.pulse_acc_kg = 0;
      sto_update_item(sto_mtidx(pulse_acc_0d1g), (const Sto_CellUnion *)&pgv->ir.meas_ca.pulse_acc_0d1g, 2);
    }

    return;
  }

  pgv->ir.meas_ca.pulse_acc_0d1g += flowrate_0d1g_0d01s;
  pgv->ir.meas_ca.pulse_acc_kg = pgv->ir.meas_ca.pulse_acc_0d1g / 10000;

  force_save = 0;

  set_0d1g = pgv->hr.meas_pa.weight_pulse_set_kg * 10000;

  if(pgv->ir.meas_ca.pulse_acc_0d1g >= set_0d1g)
  {
    pgv->ir.meas_ca.pulse_acc_0d1g -= set_0d1g;

//    pulse_send();

    force_save = 1;
  }

  if((step++ > 99) || (force_save == 1))
  {
    step = 0;

    sto_update_item(sto_mtidx(pulse_acc_0d1g), (const Sto_CellUnion *)&pgv->ir.meas_ca.pulse_acc_0d1g, 2);
  }
}

void meas_accrue(double flowrate_0d1g_0d01s, GlobalVariablesStru *pgv)
{
  acc_keydata_stru acc_keydata;

  meas_pulse_accrue(flowrate_0d1g_0d01s, pgv);

  /* 时间无效 不做累计 */
  if(sys_datatime.effective != 1)
  {
    return;
  }

  acc_class_now(pgv, &acc_keydata);
  
  if(pgv->co.meas_ec.acc_all_clear_key == MEAS_ACC_ALL_CLEAR_KEY)
  {
    pgv->co.meas_ec.acc_all_clear_key = 0;
    
    acc_total_clear(pgv, &acc_keydata, 1);
    acc_year_clear(pgv,  &acc_keydata, 1);
    acc_month_clear(pgv, &acc_keydata, 1);
    acc_day_clear(pgv,   &acc_keydata, 1);
    acc_hour_clear(pgv,  &acc_keydata, 1);
    acc_class_clear(pgv, &acc_keydata, 1);
  }
  
  meas_interval_accrue(flowrate_0d1g_0d01s, pgv);
  
  meas_tymd_accrue(flowrate_0d1g_0d01s, pgv, &acc_keydata);

  meas_class_accrue(flowrate_0d1g_0d01s, pgv, &acc_keydata);
}
